// tUtil.cpp: implementation of the tUtil class.
//
//////////////////////////////////////////////////////////////////////

// RCS Info
static char *rcsid = "$Id: tUtil.cpp,v 1.9 2004/01/30 13:41:53 almendra Exp $";
static char *rcsname = "$Name:  $";


#include <assert.h>
#include <process.h>

#include "tUtil.h"
#include "tLuaCOMException.h"

tStringBuffer tUtil::string_buffer = tStringBuffer();
FILE* tUtil::log_file = NULL;

#define MAX_VALID_STRING_SIZE 1000

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

bool tUtil::IsValidString(LPCTSTR string)
{
  bool return_value = string != NULL &&
    !IsBadStringPtr(string, MAX_VALID_STRING_SIZE);

  assert(return_value);

  return return_value;
}

const char *tUtil::GetErrorMessage(DWORD errorcode)
{
  LPVOID lpMsgBuf;
  DWORD result = 0;

  result = FormatMessage( 
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    errorcode,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL);

  if(result == 0)
    return NULL;

  tUtil::string_buffer.copyToBuffer((char *) lpMsgBuf);

  // Free the buffer.
  LocalFree( lpMsgBuf );

  return tUtil::string_buffer.getBuffer();
}

const char * tUtil::bstr2string(BSTR bstr)
{
  char* str = NULL;
  long size = 0;
  int result = 0;

  try
  {
    if(bstr != NULL)
    {
      // gets the size of the buffer
      size = WideCharToMultiByte(
        CP_UTF8,            // code page
        0,            // performance and mapping flags
        bstr,    // wide-character string
        -1,          // number of chars in string
        str,     // buffer for new string
        0,          // size of buffer
        NULL,     // default for unmappable chars
        NULL  // set when default char used
      );

      if(!size)
        LUACOM_ERROR(tUtil::GetErrorMessage(GetLastError()));

      str = new char[size];

      result = WideCharToMultiByte(
        CP_UTF8,            // code page
        0,            // performance and mapping flags
        bstr,    // wide-character string
        -1,          // number of chars in string
        str,     // buffer for new string
        size,          // size of buffer
        NULL,     // default for unmappable chars
        NULL  // set when default char used
      );

      if(!result)
        LUACOM_ERROR(tUtil::GetErrorMessage(GetLastError()));

    }
    else
    {
      str = new char[1];
      str[0] = '\0';
    }
  }
  catch(class tLuaCOMException& e)
  {
    UNUSED(e);

    if(str)
      delete str;

    str = new char[1];
    str[0] = '\0';
  }

  tUtil::string_buffer.copyToBuffer(str);

  delete str;

  return tUtil::string_buffer.getBuffer();
}

BSTR tUtil::string2bstr(const char * string)
{
  if(!string)
    return NULL;

  BSTR bstr;

  long length = 
    MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);

  try
  {
    if(length == 0)
      LUACOM_ERROR(tUtil::GetErrorMessage(GetLastError()));
  }
  catch(class tLuaCOMException& e)
  {
    UNUSED(e);

    return NULL;
  }

  wchar_t *widestr = new wchar_t[length];

  MultiByteToWideChar(CP_UTF8, 0, string, -1, widestr, length);

  bstr = SysAllocString(widestr);

  delete widestr;
  widestr = NULL;

  return bstr;
}

bool tUtil::OpenLogFile(const char *name)
{
  tUtil::CloseLogFile();

  tUtil::log_file = fopen(name, "w");

  if(!tUtil::log_file)
    return false;
  else
    return true;
}

void tUtil::CloseLogFile()
{
  if(tUtil::log_file)
  {
    fclose(tUtil::log_file);
    tUtil::log_file = NULL;
  }
}

void tUtil::log(const char *who, const char *what, ...)
{
  if(tUtil::log_file && who && what)
  {
    fprintf(tUtil::log_file, "%s:", who);

    va_list marker;
    va_start(marker, what);

    vfprintf(tUtil::log_file, what, marker);

    va_end(marker);

    if(what[strlen(what) - 1] != '\n')
      fprintf(tUtil::log_file, "\n");

    fflush(tUtil::log_file);
  }
}

void tUtil::log_verbose(const char *who, const char *what, ...)
{
#ifdef VERBOSE
  if(tUtil::log_file && who && what)
  {
    fprintf(tUtil::log_file, "%s:", who);

    va_list marker;
    va_start(marker, what);

    vfprintf(tUtil::log_file, what, marker);

    va_end(marker);

    if(what[strlen(what) - 1] != '\n')
      fprintf(tUtil::log_file, "\n");

    fflush(tUtil::log_file);
  }
#endif
}


char * tUtil::strdup(const char *string)
{
  if(!string)
    return NULL;

  char *new_string = (char *) malloc(strlen(string)+1);

  strcpy(new_string, string);

  return new_string;
}

void tUtil::ShowHelp(const char *filename, unsigned long context)
{
  // filename must have at least the extension
  if(!filename || strlen(filename) < 5)
    return;

  const char* extension = &filename[strlen(filename) - 4];

  if(_stricmp(extension, ".chm") == 0)
  {
    char context_param[50];
  
    if(context != 0)
      sprintf(context_param, "-mapid %d", context);
    else
      context_param[0] = '\0';
  
    _spawnlp(_P_NOWAIT, "hh.exe", "hh.exe", context_param, filename, NULL);
  }
  else if(_stricmp(extension, ".hlp") == 0)
  {
    if(context != 0)
      WinHelp(NULL, filename, HELP_CONTEXT, context);
    else
      WinHelp(NULL, filename, HELP_FINDER, 0);
  }
}
